<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/openlayers/9.2.4/ol.min.css"
    integrity="sha512-bc9nJM5uKHN+wK7rtqMnzlGicwJBWR11SIDFJlYBe5fVOwjHGtXX8KMyYZ4sMgSL0CoUjo4GYgIBucOtqX/RUQ=="
    crossorigin="anonymous" referrerpolicy="no-referrer" />
  <title>Openlayers地图各种控件的使用</title>

  <style>
    * {
      margin: 0;
      padding: 0;
      box-sizing: border-box;
    }

    html,
    body,
    #app,
    .app-map {
      height: 100%;
      height: 100%;
    }

    .app-btns {
      position: fixed;
      right: 10px;
      top: 50%;
      background-color: #fff;
      box-shadow: 0 2px 12px 0 rgba(0, 0, 0, .5);
      width: 210px;
      padding: 25px;
      text-align: center;
      border-radius: 5px;
      z-index: 2;
      transform: translateY(-50%);
    }

    #app .app-btns .ctrl {
      position: relative;
      width: 100%;
      height: 100%;
      background-color: transparent;
    }

    .app-btns .contorl button {
      font-size: 16px;
      border: none;
      padding: 0px 15px;
      border-radius: 0px;
      color: #fff;
      background-color: #409eff;
      border-color: #409eff;
      cursor: pointer;
      border: none;
      margin-bottom: 5px;
      line-height: 40px;
      height: 40px;
      width: 100%;
    }

    #app .app-btns button:focus,
    #app .app-btns button:hover {
      background: #66b1ff;
      border-color: #66b1ff;
      color: #fff;
      outline: none;
    }

    .app-btns .contorl {
      height: 40px;
      width: 100%;
      margin-bottom: 10px;
    }

    #zoom-to-extent button {
      width: 100%;
    }

    #zoom .ctrl {
      display: flex;
    }

    #mouse-position {
      position: relative;
      text-align: center;
    }

    #mouse-position .ol-mouse-position {
      top: 0;
      right: 0;
      position: relative;
      height: 40px;
      line-height: 40px;
      background-color: #409eff;
      border-color: #409eff;
      color: #fff;
      font-size: 16px;
    }

    #rotate {
      position: relative;
      display: flex;
    }

    #rotate .ol-rotate {
      position: relative;
      top: 0;
      right: 0;
      bottom: 0;
      width: 50%;
    }

    #rotate .ol-rotate button {
      margin: 0;
    }

    #rotate .manual-rorate {
      width: 50%;
    }

    #scale-line {
      position: relative;
      height: 60px;
    }

    #scale-line .ol-scale-bar {
      position: absolute;
      left: 50%;
      top: 50%;
      transform: translate(-50%, -50%);
    }

    #zoom-slider {
      position: relative;
      height: auto;
    }

    #zoom-slider .ol-zoomslider {
      top: 0;
      left: 0;
      height: 200px;
      position: relative;
      width: 36px;
      margin: 0 auto;
    }

    #zoom-slider .ol-zoomslider button {
      margin-bottom: 0;
      margin: 0;
    }

    #overview-map {
      position: relative;
      height: 150px;
    }

    #overview-map .ol-overviewmap {
      left: 5px;
      bottom: 0;
    }

    .ol-attribution,
    #attribution {
      height: 40px;
      line-height: 40px;
    }

    #rotate .ol-control,
    #attribution .ol-control {
      background-color: transparent;
    }
  </style>

</head>

<body>
  <div id="app">
    <div class="app-map" id="app-map">
      <div class="app-btns">
        <div class="contorl" id="zoom-to-extent"></div>
        <div class="contorl" id="zoom"></div>
        <div class="contorl" id="full-screen"></div>
        <div class="contorl" id="mouse-position"></div>
        <div class="contorl" id="rotate">
          <button @click='handleClickRotateMap' type="button" class="manual-rorate">旋转</button>
        </div>
        <div class="contorl" id="scale-line"></div>
        <div class="contorl" id="zoom-slider"></div>
        <div id="overview-map"></div>
        <div id="attribution"></div>
      </div>
    </div>
  </div>

  <script src="https://cdnjs.cloudflare.com/ajax/libs/openlayers/9.2.4/dist/ol.min.js"
    integrity="sha512-xXS2hdEzrUC2BFO0fIJ+d/bwScOLgN+W7psE4XXq6xULXjKFCskUNe8QOVVUsB7vtYRI5ZS0Ie4EgS4VzJQBkQ=="
    crossorigin="anonymous" referrerpolicy="no-referrer"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/vue/3.4.14/vue.global.prod.min.js"
    integrity="sha512-huEQFMCpBzGkSDSPVAeQFMfvWuQJWs09DslYxQ1xHeaCGQlBiky9KKZuXX7zfb0ytmgvfpTIKKAmlCZT94TAlQ=="
    crossorigin="anonymous" referrerpolicy="no-referrer"></script>

  <script>
    const { createApp } = Vue;
    const vm = createApp({
      data() {
        return {
          map: {}
        }
      },
      methods: {
        // 初始化地图
        initMap() {
          const attributions = '<a href="https://ditu.amap.com/" target="_blank">&copy; 地图版权归高德地图所有</a>';
          // 图层资源
          const source = new ol.source.XYZ({
            attributions: attributions,
            url: 'http://wprd04.is.autonavi.com/appmaptile?lang=zh_cn&size=1&style=7&x={x}&y={y}&z={z}'
          });
          // 高德地图瓦片地址
          const mainLayer = new ol.layer.Tile({
            source
          });
          //  初始化地图
          this.map = new ol.Map({
            target: 'app-map',
            layers: [mainLayer],
            controls: ol.control.defaults.defaults({
              zoom: true, // 放大缩小工具
              zoomOptions: {
                zoomInLabel: '放大 +', // 放大按钮文本
                zoomInTipLabel: '点击放大', // 放大按钮title
                zoomOutLabel: '缩小 -', // 缩小按钮文本
                zoomOutTipLabel: '点击缩小', // 缩小按钮title
                target: 'zoom', // 父元素ID
                className: 'ctrl', // 自定义类名
                duration: 500, // 动画效果的持续时间
                delta: 0.1 // 每次点击放大缩小的层级，默认为1
              },
              rotate: true, // 旋转工具
              rotateOptions: {
                tipLabel: '摆正', // title文本
                autoHide: false, // 角度为0的时候是否自动隐藏
                target: 'rotate', // 父元素ID
                compassClassName: 'icon', // 旋转图标的自定义类名
                duration: 250, // 旋转动画的持续时间
                resetNorth: (a) => { // 默认是点击后旋转到0度，可自定义点击后的操作，可以覆盖原有的
                  this.map.getView().setRotation(0);
                }
              },
              attribution: true, // 地图版权信息工具
              attributionOptions: {
                target: 'attribution', // 父元素ID
                collapsed: false, // 默认折叠
                collapsible: true // 是否可折叠，显示折叠按钮 106.577545 29.565593
              }
            }).extend([
              // 全屏退出全屏工具
              new ol.control.FullScreen({
                label: '全屏', // 全屏按钮文本
                labelActive: '退出全屏', // 退出全屏按钮文本
                tipLabel: '全屏/退出全屏', // 按钮title
                className: 'ctrl', // 自定义类名
                target: 'full-screen', // 父元素ID
                activeClassName: 'is-full', // 全屏状态下按钮自定义类名
                inactiveClassName: 'not-full' // 不是全屏状态下按钮自定义类名
              }),
              // 比例尺工具
              new ol.control.ScaleLine({
                bar: true, // 展示为柱状，默认是直线
                text: true, // 显示比例尺数字 1:421,111,348，当bar为true是生效
                units: 'metric', // 单位，默认米制 {'degrees'} {'imperial'} {'nautical'} {'metric'} {'us'}
                // className: 'sccale-line', // 自定义类名
                steps: 4, // 柱状的比例尺时，将柱状分为几段，默认4
                target: 'scale-line'// 父元素ID
              }),
              // 缩放滑块工具
              // https://openlayers.org/en/v8.1.0/examples/zoomslider.html
              new ol.control.ZoomSlider({
                // className: 'ol-zoomslider ol-zoomslider-custom', // 自定义类名
                duration: 500, // 缩放动画执行时间
                target: 'zoom-slider' // 父元素ID
              }),
              // 小地图工具
              new ol.control.OverviewMap({
                target: 'overview-map', // 父元素ID
                className: 'ol-overviewmap ol-overviewmap-custom', // 自定义类名
                collapsed: false, // 默认折叠
                collapsible: true, // 是否可折叠，显示折叠按钮
                label: 'op', // 展开的文本
                collapseLabel: 'cl', // 折叠的文本
                rotateWithView: false, // 是否跟着地图旋转
                tipLabel: '小地图', // 文本的title
                layers: [ // 小地图内部的图层
                  new ol.layer.Tile({
                    source: new ol.source.XYZ({
                      url: 'http://wprd04.is.autonavi.com/appmaptile?lang=zh_cn&size=1&style=7&x={x}&y={y}&z={z}'
                    })
                  })
                ]
              }),
              // 恢复到置顶视图工具
              new ol.control.ZoomToExtent({
                extent: [7108532.525146691, 2150882.129043405, 16501114.56082915, 6646602.384664332], // 恢复视图的经纬度范围
                label: '恢复默认视图', // 展示的文本
                tipLabel: '点击恢复默认视图', // title文本
                target: 'zoom-to-extent', // id 或者DOM document.getElementById('zoomToExtent')
                className: 'zoomToExtent ctrl' // 自定义类名
              }),
              // 展示鼠标经纬度工具
              new ol.control.MousePosition({
                projection: 'EPSG:4326', // 经纬度的坐标系
                coordinateFormat: function (coordinate) { // 格式化经纬度
                  return '(' + coordinate.map(e => {
                    return e.toFixed(3)
                  }).join(',') + ')';
                },
                target: 'mouse-position', // 父元素ID
                placeholder: '鼠标不在地图范围内'
              })
            ]),
            view: new ol.View({
              projection: 'EPSG:3857',
              center: ol.proj.transform([106.04453415000009, 36.70986324334069], 'EPSG:4326', 'EPSG:3857'),
              zoom: 10
            })
          });
          window.aa = this.map;
        },
        // 点击旋转地图
        handleClickRotateMap() {
          this.map.getView().setRotation(Math.floor(Math.random() * (2 * Math.PI)));
        }
      },
      mounted() {
        this.initMap();
      }
    }).mount('#app')
  </script>

</body>

</html>